package com.mvc.rpc;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;

import java.util.Set;

/**
 * Rpc代理扫描
 * @author JayEinstein
 */
public class ClassPathRpcProxyScanner extends ClassPathBeanDefinitionScanner {

    /**
     * 直连地址
     */
    private String host;

    /**
     * 服务名称
     */
    private String serviceName;

    public ClassPathRpcProxyScanner(BeanDefinitionRegistry registry) {
        super(registry, false);
        registerFiler();
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    private void registerFiler() {

        // exclude package-info.java
        addExcludeFilter((metadataReader, metadataReaderFactory) -> {
            String className = metadataReader.getClassMetadata().getClassName();
            return className.endsWith("package-info");
        });

        // 只代理接口
        addIncludeFilter((metadataReader, metadataReaderFactory) -> metadataReader.getClassMetadata().isInterface());

    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

        if (beanDefinitions.isEmpty()) {
            return beanDefinitions;
        }

        for (BeanDefinitionHolder holder : beanDefinitions) {
            AbstractBeanDefinition definition = (AbstractBeanDefinition) holder.getBeanDefinition();

            String beanClassName = definition.getBeanClassName();

            // 构造方法填充
            definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);

            // 属性填充
            MutablePropertyValues propertyValues = definition.getPropertyValues();
            Class proxyClass = null;
            try {
                proxyClass = Class.forName(beanClassName);
            } catch (ClassNotFoundException e) {
                // ignore
            }
            propertyValues.add("proxyClass", proxyClass);
            propertyValues.add("host", host);
            propertyValues.add("serviceName", serviceName);

            // 其他
            definition.setBeanClass(RpcProxyFactoryBean.class);
            definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, proxyClass);
            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);

        }

        return beanDefinitions;
    }

}
